//! 特征计算工具模块
//! 
//! 提供特征计算相关的工具函数

use serde::{Deserialize, Serialize};
use crate::objects::RawBar;

/// 特征工具配置
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct FeatureUtilsConfig {
    /// 是否标准化特征
    pub normalize: bool,
    /// 是否进行特征选择
    pub feature_selection: bool,
    /// 缺失值处理方式
    pub missing_value_strategy: String,
}

/// 特征计算工具
#[derive(Debug, Clone)]
pub struct FeatureUtils {
    config: FeatureUtilsConfig,
}

impl FeatureUtils {
    /// 创建新的特征工具
    pub fn new(config: FeatureUtilsConfig) -> Self {
        Self { config }
    }

    /// 数据预处理
    pub fn preprocess_data(&self, bars: &[RawBar]) -> Vec<RawBar> {
        let mut processed_bars = bars.to_vec();
        
        // 处理缺失值
        self.handle_missing_values(&mut processed_bars);
        
        // 数据清洗
        self.clean_data(&mut processed_bars);
        
        processed_bars
    }

    /// 处理缺失值
    fn handle_missing_values(&self, bars: &mut Vec<RawBar>) {
        if bars.is_empty() {
            return;
        }
        
        match self.config.missing_value_strategy.as_str() {
            "forward_fill" => {
                for i in 1..bars.len() {
                    if bars[i].open == 0.0 || bars[i].close == 0.0 {
                        bars[i].open = bars[i-1].open;
                        bars[i].close = bars[i-1].close;
                        bars[i].high = bars[i-1].high;
                        bars[i].low = bars[i-1].low;
                    }
                }
            }
            "interpolate" => {
                self.interpolate_missing_values(bars);
            }
            "drop" => {
                bars.retain(|bar| bar.open != 0.0 && bar.close != 0.0);
            }
            _ => {
                // 默认使用前向填充
                for i in 1..bars.len() {
                    if bars[i].open == 0.0 || bars[i].close == 0.0 {
                        bars[i].open = bars[i-1].open;
                        bars[i].close = bars[i-1].close;
                        bars[i].high = bars[i-1].high;
                        bars[i].low = bars[i-1].low;
                    }
                }
            }
        }
    }

    /// 插值处理缺失值
    fn interpolate_missing_values(&self, bars: &mut Vec<RawBar>) {
        let mut i = 0;
        while i < bars.len() {
            if bars[i].open == 0.0 || bars[i].close == 0.0 {
                // 找到下一个有效值
                let mut next_valid = i + 1;
                while next_valid < bars.len() && 
                      (bars[next_valid].open == 0.0 || bars[next_valid].close == 0.0) {
                    next_valid += 1;
                }
                
                if next_valid < bars.len() {
                    // 线性插值
                    let prev_valid = if i > 0 { i - 1 } else { next_valid };
                    let steps = next_valid - prev_valid;
                    
                    for j in prev_valid + 1..next_valid {
                        let ratio = (j - prev_valid) as f64 / steps as f64;
                        bars[j].open = bars[prev_valid].open + 
                                      (bars[next_valid].open - bars[prev_valid].open) * ratio;
                        bars[j].close = bars[prev_valid].close + 
                                       (bars[next_valid].close - bars[prev_valid].close) * ratio;
                        bars[j].high = bars[prev_valid].high + 
                                      (bars[next_valid].high - bars[prev_valid].high) * ratio;
                        bars[j].low = bars[prev_valid].low + 
                                     (bars[next_valid].low - bars[prev_valid].low) * ratio;
                    }
                    i = next_valid;
                } else {
                    i += 1;
                }
            } else {
                i += 1;
            }
        }
    }

    /// 数据清洗
    fn clean_data(&self, bars: &mut Vec<RawBar>) {
        bars.retain(|bar| {
            // 移除异常值
            bar.open > 0.0 && bar.close > 0.0 && 
            bar.high >= bar.low && 
            bar.high >= bar.open && bar.high >= bar.close &&
            bar.low <= bar.open && bar.low <= bar.close
        });
    }

    /// 特征标准化
    pub fn normalize_features(&self, features: &[f64]) -> Vec<f64> {
        if features.is_empty() {
            return vec![];
        }
        
        let mean: f64 = features.iter().sum::<f64>() / features.len() as f64;
        let variance: f64 = features.iter()
            .map(|x| (x - mean).powi(2))
            .sum::<f64>() / features.len() as f64;
        let std_dev = variance.sqrt();
        
        if std_dev == 0.0 {
            return features.iter().map(|_| 0.0).collect();
        }
        
        features.iter()
            .map(|x| (x - mean) / std_dev)
            .collect()
    }

    /// 特征选择
    pub fn select_features(&self, features: &[Vec<f64>], labels: &[f64]) -> Vec<usize> {
        if features.is_empty() || labels.is_empty() {
            return vec![];
        }
        
        // 简单的特征选择：基于与标签的相关性
        let mut feature_scores = Vec::new();
        
        for (i, feature) in features.iter().enumerate() {
            if feature.len() == labels.len() {
                let correlation = self.calculate_correlation(feature, labels);
                feature_scores.push((i, correlation.abs()));
            }
        }
        
        // 按相关性排序，选择前50%的特征
        feature_scores.sort_by(|a, b| b.1.partial_cmp(&a.1).unwrap());
        let selected_count = (feature_scores.len() / 2).max(1);
        
        feature_scores.into_iter()
            .take(selected_count)
            .map(|(index, _)| index)
            .collect()
    }

    /// 计算相关系数
    fn calculate_correlation(&self, x: &[f64], y: &[f64]) -> f64 {
        if x.len() != y.len() || x.is_empty() {
            return 0.0;
        }
        
        let n = x.len() as f64;
        let sum_x: f64 = x.iter().sum();
        let sum_y: f64 = y.iter().sum();
        let sum_xy: f64 = x.iter().zip(y.iter()).map(|(a, b)| a * b).sum();
        let sum_x2: f64 = x.iter().map(|a| a * a).sum();
        let sum_y2: f64 = y.iter().map(|a| a * a).sum();
        
        let numerator = n * sum_xy - sum_x * sum_y;
        let denominator = ((n * sum_x2 - sum_x * sum_x) * (n * sum_y2 - sum_y * sum_y)).sqrt();
        
        if denominator == 0.0 {
            0.0
        } else {
            numerator / denominator
        }
    }

    /// 计算技术指标特征
    pub fn calculate_technical_features(&self, bars: &[RawBar]) -> Vec<Vec<f64>> {
        if bars.is_empty() {
            return vec![];
        }
        
        let prices: Vec<f64> = bars.iter().map(|bar| bar.close).collect();
        let highs: Vec<f64> = bars.iter().map(|bar| bar.high).collect();
        let lows: Vec<f64> = bars.iter().map(|bar| bar.low).collect();
        let volumes: Vec<f64> = bars.iter().map(|bar| bar.vol).collect();
        
        let mut features = Vec::new();
        
        // 价格变化率
        let price_changes = self.calculate_price_changes(&prices);
        features.push(price_changes);
        
        // 成交量变化率
        let volume_changes = self.calculate_price_changes(&volumes);
        features.push(volume_changes);
        
        // 价格位置（相对于最高最低价）
        let price_positions = self.calculate_price_positions(&prices, &highs, &lows);
        features.push(price_positions);
        
        // 波动率
        let volatilities = self.calculate_volatilities(&prices, 20);
        features.push(volatilities);
        
        features
    }

    /// 计算价格变化率
    fn calculate_price_changes(&self, prices: &[f64]) -> Vec<f64> {
        if prices.len() < 2 {
            return vec![];
        }
        
        let mut changes = Vec::new();
        for i in 1..prices.len() {
            let change = if prices[i-1] != 0.0 {
                (prices[i] - prices[i-1]) / prices[i-1]
            } else {
                0.0
            };
            changes.push(change);
        }
        changes
    }

    /// 计算价格位置
    fn calculate_price_positions(&self, prices: &[f64], highs: &[f64], lows: &[f64]) -> Vec<f64> {
        if prices.is_empty() || highs.is_empty() || lows.is_empty() {
            return vec![];
        }
        
        let mut positions = Vec::new();
        for i in 0..prices.len() {
            if highs[i] != lows[i] {
                let position = (prices[i] - lows[i]) / (highs[i] - lows[i]);
                positions.push(position);
            } else {
                positions.push(0.5);
            }
        }
        positions
    }

    /// 计算波动率
    fn calculate_volatilities(&self, prices: &[f64], window: usize) -> Vec<f64> {
        if prices.len() < window {
            return vec![];
        }
        
        let mut volatilities = Vec::new();
        for i in window - 1..prices.len() {
            let window_prices = &prices[i - window + 1..=i];
            let returns: Vec<f64> = window_prices.windows(2)
                .map(|w| (w[1] - w[0]) / w[0])
                .collect();
            
            let mean_return: f64 = returns.iter().sum::<f64>() / returns.len() as f64;
            let variance: f64 = returns.iter()
                .map(|r| (r - mean_return).powi(2))
                .sum::<f64>() / returns.len() as f64;
            let volatility = variance.sqrt();
            volatilities.push(volatility);
        }
        volatilities
    }

    /// 生成特征报告
    pub fn generate_feature_report(&self, bars: &[RawBar]) -> serde_json::Value {
        let processed_bars = self.preprocess_data(bars);
        let technical_features = self.calculate_technical_features(&processed_bars);
        
        serde_json::json!({
            "original_count": bars.len(),
            "processed_count": processed_bars.len(),
            "feature_count": technical_features.len(),
            "feature_dimensions": technical_features.iter().map(|f| f.len()).collect::<Vec<usize>>(),
            "data_quality": {
                "missing_values_handled": bars.len() - processed_bars.len(),
                "normalization_applied": self.config.normalize,
                "feature_selection_applied": self.config.feature_selection
            },
            "feature_statistics": {
                "price_changes": if !technical_features.is_empty() {
                    let changes = &technical_features[0];
                    serde_json::json!({
                        "mean": changes.iter().sum::<f64>() / changes.len() as f64,
                        "std": self.calculate_std(changes),
                        "min": changes.iter().fold(f64::INFINITY, |a, &b| a.min(b)),
                        "max": changes.iter().fold(f64::NEG_INFINITY, |a, &b| a.max(b))
                    })
                } else {
                    serde_json::Value::Null
                }
            }
        })
    }

    /// 计算标准差
    fn calculate_std(&self, values: &[f64]) -> f64 {
        if values.is_empty() {
            return 0.0;
        }
        
        let mean: f64 = values.iter().sum::<f64>() / values.len() as f64;
        let variance: f64 = values.iter()
            .map(|x| (x - mean).powi(2))
            .sum::<f64>() / values.len() as f64;
        variance.sqrt()
    }
}

#[cfg(test)]
mod tests {
    use super::*;
    use crate::objects::{RawBar, Freq};
    use chrono::Utc;

    #[test]
    fn test_normalize_features() {
        let config = FeatureUtilsConfig {
            normalize: true,
            feature_selection: false,
            missing_value_strategy: "forward_fill".to_string(),
        };
        let utils = FeatureUtils::new(config);
        
        let features = vec![1.0, 2.0, 3.0, 4.0, 5.0];
        let normalized = utils.normalize_features(&features);
        
        assert_eq!(normalized.len(), features.len());
        // 标准化后的均值应该接近0
        let mean: f64 = normalized.iter().sum::<f64>() / normalized.len() as f64;
        assert!(mean.abs() < 1e-10);
    }

    #[test]
    fn test_calculate_correlation() {
        let config = FeatureUtilsConfig {
            normalize: true,
            feature_selection: false,
            missing_value_strategy: "forward_fill".to_string(),
        };
        let utils = FeatureUtils::new(config);
        
        let x = vec![1.0, 2.0, 3.0, 4.0, 5.0];
        let y = vec![2.0, 4.0, 6.0, 8.0, 10.0];
        let correlation = utils.calculate_correlation(&x, &y);
        
        assert!((correlation - 1.0).abs() < 1e-10);
    }

    #[test]
    fn test_preprocess_data() {
        let config = FeatureUtilsConfig {
            normalize: true,
            feature_selection: false,
            missing_value_strategy: "forward_fill".to_string(),
        };
        let utils = FeatureUtils::new(config);
        
        let bars = vec![
            RawBar {
                symbol: "TEST".to_string(),
                id: 1,
                freq: Freq::Day,
                dt: Utc::now(),
                open: 100.0,
                close: 110.0,
                high: 115.0,
                low: 95.0,
                vol: 1000.0,
                amount: 110000.0,
                cache: Default::default(),
            }
        ];
        
        let processed = utils.preprocess_data(&bars);
        assert_eq!(processed.len(), bars.len());
    }
} 